package leetcode.tree;

import java.util.Objects;

/**
 * 序列化是将一个数据结构或者对象转换为连续的比特位的操作，进而可以将转换后的数据存储在一个文件或者内存中，同时也可以通过网络传输到另一个计算机环境，采取相反方式重构得到原数据。
 * <p>
 * 请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑，你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
 * <p>
 * 前序遍历带空值节点序列化
 */
public class LeetCode297_Codec {

    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        StringBuilder r = new StringBuilder();
        s(root, r);
        return r.toString();
    }

    public void s(TreeNode root, StringBuilder r) {
        if (root == null) {
            r.append("#,");
            return;
        }
        r.append(root.val).append(",");
        s(root.left, r);
        s(root.right, r);
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        if (data == null) {
            return null;
        }
        String[] s = data.split(",");
        if (s.length < 1) {
            return null;
        }
        if ("#".equals(s[0])) {
            return null;
        }
        TreeNode root = new TreeNode(Integer.parseInt(s[0]));
        d(root, s);

        return root;
    }

    public TreeNode deserialize2(String data) {
        if (data == null) {
            return null;
        }
        String[] s = data.split(",");
        if (s.length < 1) {
            return null;
        }

        return d2(s);
    }

    private static int curIndex = 1;

    public void d(TreeNode root, String[] s) {
        if (root == null) {
            return;
        }
        if (curIndex < s.length) {
            TreeNode l, r;
            if (!Objects.equals(s[curIndex], "#")) {
                l = new TreeNode(Integer.parseInt(s[curIndex++]));
                root.left = l;
                d(l, s);
            } else {
                curIndex++;
            }
            if (!Objects.equals(s[curIndex], "#")) {
                r = new TreeNode(Integer.parseInt(s[curIndex++]));
                root.right = r;
                d(r, s);
            } else {
                curIndex++;
            }
        }
    }

    private static int cnt = 0;

    public TreeNode d2(String[] s) {
        String s1 = s[cnt++];
        if (Objects.equals(s1, "#")) {
            return null;
        } else {
            TreeNode head = new TreeNode(Integer.parseInt(s1));
            head.left = d2(s);
            head.right = d2(s);
            return head;
        }
    }

    public static void main(String[] args) {
        TreeNode t1 = new TreeNode(1);
        TreeNode t2 = new TreeNode(2);
        TreeNode t3 = new TreeNode(3);
        TreeNode t4 = new TreeNode(4);
        TreeNode t5 = new TreeNode(5);

        t1.left = t2;
        t3.left = t4;

        t1.right = t3;
        t3.right = t5;

        LeetCode297_Codec leetCode297Codec = new LeetCode297_Codec();
        System.out.println("serialize = " + leetCode297Codec.serialize(t1));
        TreeNode deserialize = leetCode297Codec.deserialize("1,2,#,#,3,4,#,#,5,#,#,");
        System.out.println("deserialize = " + deserialize);

        TreeNode treeNode = leetCode297Codec.deserialize2("1,2,#,#,3,4,#,#,5,#,#,");
        System.out.println("treeNode = " + treeNode);

    }

}
